package site.edody.dframe.plugin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 动态方法调用工具类
 * 提供通过类名、方法名和参数列表来动态调用方法的功能
 */
public class DynamicMethodInvoker {

    private final CodeBasedDependencyManager dependencyManager;
    private static final Logger log = LoggerFactory.getLogger(DynamicMethodInvoker.class);

    public DynamicMethodInvoker(CodeBasedDependencyManager dependencyManager) {
        this.dependencyManager = dependencyManager;
    }

    /**
     * 动态实例化类（支持带参数的构造函数）
     */
    public Object instantiateClass(String className, ArrayList<Object> params) throws Exception {
        Class<?> clazz = dependencyManager.loadClass(className);
        return instantiateWithConstructor(clazz, params);
    }

    /**
     * 动态实例化类（无参构造函数）
     */
    public Object instantiateClass(String className) throws Exception {
        return instantiateClass(className, null);
    }

    /**
     * 直接使用Class对象实例化类（支持带参数的构造函数）
     */
    public Object instantiateClass(Class<?> clazz, ArrayList<Object> params) throws Exception {
        return instantiateWithConstructor(clazz, params);
    }

    /**
     * 直接使用Class对象实例化类（无参构造函数）
     */
    public Object instantiateClass(Class<?> clazz) throws Exception {
        return instantiateClass(clazz, null);
    }


    /**
     * 通过构造函数实例化对象
     */
    private Object instantiateWithConstructor(Class<?> clazz, ArrayList<Object> params) throws Exception {
        Constructor<?>[] constructors = clazz.getConstructors();
        Constructor<?> targetConstructor = null;

        // 如果参数为空，尝试使用无参构造函数
        if (params == null || params.isEmpty()) {
            try {
                return clazz.getDeclaredConstructor().newInstance();
            } catch (NoSuchMethodException e) {
                // 继续查找其他构造函数
            }
        }

        // 查找匹配的构造函数
        for (Constructor<?> constructor : constructors) {
            Class<?>[] paramTypes = constructor.getParameterTypes();

            if (paramTypes.length == (params == null ? 0 : params.size())) {
                boolean compatible = true;
                if (params != null) {
                    for (int i = 0; i < params.size(); i++) {
                        Object param = params.get(i);
                        Class<?> paramType = paramTypes[i];

                        if (param != null && !isCompatibleType(paramType, param.getClass())) {
                            compatible = false;
                            break;
                        }
                    }
                }

                if (compatible) {
                    targetConstructor = constructor;
                    break;
                }
            }
        }

        if (targetConstructor == null) {
            // 提供更详细的错误信息
            StringBuilder errorMsg = new StringBuilder();
            errorMsg.append("未找到匹配的构造函数。类: ").append(clazz.getName())
                    .append(", 参数: ");
            if (params != null) {
                for (int i = 0; i < params.size(); i++) {
                    Object param = params.get(i);
                    errorMsg.append("参数").append(i).append(": ")
                            .append(param != null ? param.getClass().getName() : "null");
                    if (i < params.size() - 1) {
                        errorMsg.append(", ");
                    }
                }
            }
            throw new NoSuchMethodException(errorMsg.toString());
        }

        return targetConstructor.newInstance(params == null ? new Object[0] : params.toArray());
    }


    /**
     * 动态调用静态方法
     */
    public Object invokeStaticMethod(String className, String methodName, ArrayList<Object> params) throws Exception {
        Class<?> clazz = dependencyManager.loadClass(className);
        return invokeMethod(clazz, null, methodName, params);
    }

    /**
     * 动态调用实例方法
     */
    public Object invokeInstanceMethod(Object target, String methodName, ArrayList<Object> params) throws Exception {
        return invokeMethod(target.getClass(), target, methodName, params);
    }

    /**
     * 通用方法调用实现
     */
    private Object invokeMethod(Class<?> clazz, Object target, String methodName, ArrayList<Object> params) throws Exception {
        Method targetMethod = findBestMatchingMethod(clazz, methodName, params);
        return targetMethod.invoke(target, params == null ? new Object[0] : params.toArray());
    }

    /**
     * 查找最佳匹配的方法（增强版）
     */
    private Method findBestMatchingMethod(Class<?> clazz, String methodName, ArrayList<Object> params) throws Exception {
        log.debug("查找方法: {}.{}, 参数数量: {}",
                clazz.getName(), methodName,
                (params == null ? 0 : params.size()));

        Method[] methods = clazz.getMethods();
        List<Method> candidateMethods = new ArrayList<>();

        // 第一步：按名称筛选
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                candidateMethods.add(method);
                log.debug("候选方法: {}", method);
            }
        }

        if (candidateMethods.isEmpty()) {
            throw new NoSuchMethodException("方法 " + methodName + " 不存在");
        }

        // 第二步：精确匹配参数
        Method exactMatch = findExactMatch(candidateMethods, params);
        if (exactMatch != null) {
            log.debug("找到精确匹配的方法: {}", exactMatch);
            return exactMatch;
        }

        // 第三步：兼容匹配参数
        Method compatibleMatch = findCompatibleMatch(candidateMethods, params);
        if (compatibleMatch != null) {
            log.debug("找到兼容匹配的方法: {}", compatibleMatch);
            return compatibleMatch;
        }

        // 第四步：如果没有参数，返回第一个候选方法
        if (params == null || params.isEmpty()) {
            return candidateMethods.get(0);
        }

        // 第五步：提供详细的错误信息
        StringBuilder errorMsg = new StringBuilder();
        errorMsg.append("方法 ").append(methodName).append(" 未找到匹配的重载版本。\n");
        errorMsg.append("类: ").append(clazz.getName()).append("\n");
        errorMsg.append("参数: ");
        if (params != null) {
            for (int i = 0; i < params.size(); i++) {
                Object param = params.get(i);
                errorMsg.append("参数").append(i).append(": ")
                        .append(param != null ? param.getClass().getName() : "null");
                if (param != null) {
                    errorMsg.append(" (加载器: ").append(param.getClass().getClassLoader()).append(")");
                }
                if (i < params.size() - 1) {
                    errorMsg.append(", ");
                }
            }
        }
        errorMsg.append("\n候选方法:\n");
        for (Method method : candidateMethods) {
            errorMsg.append("  ").append(method).append("\n");
            Class<?>[] paramTypes = method.getParameterTypes();
            for (int i = 0; i < paramTypes.length; i++) {
                errorMsg.append("    参数").append(i).append(": ")
                        .append(paramTypes[i].getName())
                        .append(" (加载器: ").append(paramTypes[i].getClassLoader()).append(")\n");
            }
        }

        throw new NoSuchMethodException(errorMsg.toString());
    }

    /**
     * 查找精确匹配的方法（增强版）
     */
    private Method findExactMatch(List<Method> candidateMethods, ArrayList<Object> params) {
        for (Method method : candidateMethods) {
            Class<?>[] paramTypes = method.getParameterTypes();

            if (paramTypes.length == (params == null ? 0 : params.size())) {
                boolean exactMatch = true;

                if (params != null) {
                    for (int i = 0; i < params.size(); i++) {
                        Object param = params.get(i);
                        Class<?> paramType = paramTypes[i];

                        if (param != null && !isExactTypeMatch(paramType, param.getClass())) {
                            exactMatch = false;
                            break;
                        }
                    }
                }

                if (exactMatch) {
                    return method;
                }
            }
        }
        return null;
    }



    /**
     * 查找兼容匹配的方法（增强版）
     */
    private Method findCompatibleMatch(List<Method> candidateMethods, ArrayList<Object> params) {
        for (Method method : candidateMethods) {
            Class<?>[] paramTypes = method.getParameterTypes();

            if (paramTypes.length == (params == null ? 0 : params.size())) {
                boolean compatible = true;

                if (params != null) {
                    for (int i = 0; i < params.size(); i++) {
                        Object param = params.get(i);
                        Class<?> paramType = paramTypes[i];

                        if (param != null && !isCompatibleType(paramType, param.getClass())) {
                            compatible = false;
                            break;
                        }
                    }
                }

                if (compatible) {
                    return method;
                }
            }
        }
        return null;
    }




    /**
     * 检查精确类型匹配（处理类加载器问题）
     */
    private boolean isExactTypeMatch(Class<?> expected, Class<?> actual) {
        // 如果类对象相同，直接返回true
        if (expected == actual) {
            return true;
        }

        // 如果类名相同，即使类加载器不同也认为是匹配的
        if (expected.getName().equals(actual.getName())) {
            log.debug("类名相同但类加载器不同 - 认为匹配: {} (loader1: {}, loader2: {})",
                    expected.getName(),
                    expected.getClassLoader(),
                    actual.getClassLoader());
            return true;
        }

        return false;
    }


    /**
     * 检查类型兼容性
     */
    private boolean isCompatibleType(Class<?> expected, Class<?> actual) {
        // 首先检查精确匹配
        if (isExactTypeMatch(expected, actual)) {
            return true;
        }

        // 基本类型与其包装类的兼容性检查
        if (expected.isPrimitive()) {
            if (expected == boolean.class && actual == Boolean.class) return true;
            if (expected == byte.class && actual == Byte.class) return true;
            if (expected == char.class && actual == Character.class) return true;
            if (expected == short.class && actual == Short.class) return true;
            if (expected == int.class && actual == Integer.class) return true;
            if (expected == long.class && actual == Long.class) return true;
            if (expected == float.class && actual == Float.class) return true;
            if (expected == double.class && actual == Double.class) return true;
            return false;
        }

        // 非基本类型的兼容性检查
        return expected.isAssignableFrom(actual);
    }

    /**
     * 获取依赖管理器
     */
    public CodeBasedDependencyManager getDependencyManager() {
        return dependencyManager;
    }
}